<template>
	<div style="height:100%" class="con">
		<!-- 左边 -->
		<div class="selectCon">
			<div class="selectHead">
				监控位置
			</div>
			<div class="selectMain">
				<div class="select-con" v-for="item in Business" :key="item.BID">
					<div class="select">
						<el-popover placement="right" width="600" trigger="click"
							@show="selectBusiness(item.BID, item.NAME)" @hide="closePopover">
							<div v-loading="popoverLoading">
								<div class="popoverCon" v-if="popoverData.length">
									<div v-for="item in popoverData" :key="item.ip">
										<template v-if="item.available === 'N'">
											<el-tooltip placement="top" effect="light">
												<div slot="content">
													标签:{{ item.lable }}<br />IP:{{ item.ip }}
												</div>
												<i class="el-icon-video-camera" style="color:red;font-size:30px"></i>
											</el-tooltip>
										</template>
										<template v-else>
											<el-tooltip placement="top" effect="light">
												<div slot="content">
													标签:{{ item.lable }}<br />IP:{{ item.ip }}
												</div>
												<i class="el-icon-video-camera" style="color:green;font-size:30px"></i>
											</el-tooltip>
										</template>
									</div>
								</div>
								<div style="display: flex;justify-content: center;color: #c0c4cc;" v-else>
									<span>无监控节点</span>
								</div>
							</div>
							<div slot="reference">
								{{ item.NAME }}
							</div>
						</el-popover>
					</div>
				</div>
			</div>
		</div>
		<!-- 中间 -->
		<div class="graphContainer">
			<div class="graphHead">
				<el-popover title="历史浏览网络拓扑" placement="bottom" width="300" trigger="hover">
					<div class="popoverCon">
						<div v-for="item in history" :key="item">
							<div class="select" @click="selectHistoryItem(item)">
								{{ item }}
							</div>
						</div>
					</div>

					<div slot="reference">
						<div class="title">
							网络拓扑图
						</div>
					</div>
				</el-popover>

				<div v-show="!isTopFloor" class="goBack" @click="selectHistoryItem('顶层网络拓扑')">
					返回到顶层网络拓扑
				</div>
			</div>
			<div id="container" class="ScaleCSSViewport_unzoom" v-loading="loading" element-loading-text="拼命渲染中"></div>
		</div>
		<!-- 右边 -->
		<div class="warnCon">
			<div class="head">异常节点</div>
			<div class="contain">
				<div v-for="item in config.data" :key="item.ip">
					<el-tooltip placement="top" effect="light">
						<div slot="content">标签:{{ item[0] }}<br />IP:{{ item[1] }}</div>
						<i :class="item[2]==='Network'?'el-icon-jk-wangluoshebei':'el-icon-video-camera'"
							style="color:red;font-size:30px"></i>
					</el-tooltip>
				</div>
			</div>
		</div>
	</div>
</template>

<script>
	import G6 from "@antv/g6";
	import {
		getNetworktopology,
		getJavaServerNotData,
		getJavaServerData,
		submitAdmin,
	} from "@/api/index.js";
	import bus from "common/bus.js";
	import SERVER from "@/assets/img/server2.png";
	import SWITCH from "@/assets/img/Switch.png";
	import MONITOR from "@/assets/img/Monitor.png";
	import MONITORERROR from "@/assets/img/MonitorError.png";

	let getPng = (type, tag) => {
		if (type === "Monitor") {
			type = !tag ? type : type + "Error";
		}
		let nodeType = {
			["Windows"]: SERVER,
			["Network"]: SWITCH,
			["Monitor"]: MONITOR,
			["Linux"]: SERVER,
			["MonitorError"]: MONITORERROR,
		};
		return nodeType[type];
	};

	G6.registerNode("dom-node", {
		draw: (cfg, group) => {
			const shape = group.addShape(
				"image", {
					attrs: {
						width: cfg.size[0],
						height: cfg.size[1],
						img: getPng(cfg.NodeType, cfg.FAULT),
						label: cfg.label,
						shadowColor: "#f1f2f3",
						labelCfg: {
							position: "top",
							style: {
								fill: "#000",
							},
						},
					},
					draggable: true,
				},
				"image"
			);
			const text = group.addShape("text", {
				attrs: {
					text: cfg.label,
					fill: cfg.FAULT ? "#e74c3c" : "#27ae60",
					fontWeight: 400,
					textAlign: "left",
					textBaseline: "bottom",
					fontSize: 18,
				},
				name: "text-shape",
			});

			return text, shape;
		},
	});
	// const minimap = new G6.Minimap({
	//   size: [150, 100],
	// });
	const lineDash = [4, 2, 1, 2];
	G6.registerEdge(
		"line-dash", {
			afterDraw(cfg, group) {
				// if(cfg.sourceNode['_cfg'].model.parentlableport==null){

				// }
				if (
					cfg.targetNode["_cfg"].model.FAULT ||
					cfg.sourceNode["_cfg"].model.FAULT
				) {
					cfg.style.stroke = "#e74c3c";
				} else {
					// get the first shape in the group, it is the edge's path here=
					const shape = group.get("children")[0];
					let index = 0;
					// Define the animation
					shape.animate(
						() => {
							index++;
							if (index > 9) {
								index = 0;
							}
							const res = {
								lineDash,
								lineDashOffset: -index,
							};
							// returns the modified configurations here, lineDash and lineDashOffset here
							return res;
						}, {
							repeat: true, // whether executes the animation repeatly
							duration: 3000, // the duration for executing once
						}
					);
				}
			},
		},
		"cubic" // extend the built-in edge 'cubic'
	);

	export default {
		data() {
			return {
				loading: false,
				graph: "",
				graphData: [],
				Staging: [],
				selectIndex: 0,
				//选择标签
				selectLable: "",
				config: {
					data: [],
				},
				timerName: "TopologyView",
				timerEventName: "timerTopologyView",
				timerInterval: 1000 * 60,
				//是否首屏
				firstPage: true,
				//数据对比
				DataComparison: {
					lastTime: [],
					thisTime: [],
				},
				//顶层网络拓扑 数据
				switchInfo: {},
				//是否顶层网络拓扑
				isTopFloor: true,
				// 浏览记录
				history: ["顶层网络拓扑"],
				Business: [],
				popoverTitle: "",
				popoverData: [],
				popoverLoading: false,
			};
		},
		computed: {},
		created() {
			this.getFailedNode();
			this.getBusiness();
			bus.$emit("timerNewTodo", {
				name: this.timerName,
				eventName: this.timerEventName,
				interval: this.timerInterval,
				intervalNow: 0,
			});

			bus.$on(this.timerEventName, (msg) => {
				if (msg.isGetData) {
					this.getFailedNode();
					this.firstPage = false;
				}
			});
		},
		mounted() {
			this.InitChart();
		},
		methods: {
			async getSwitchInfo() {
				this.switchInfo = {};
				getNetworktopology().then((_) => {
					if (_.data.length) {
						_.data.forEach((item) => {
							this.switchInfo[item.lable] = item;
						});
						this.disposeData(_);
					} else {
						this.$message({
							type: "info",
							duration: 5000,
							message: "无网络设备节点",
						});
					}
				});
			},
			async getInfo(label) {
				this.selectLable = label;
				getJavaServerData("/Sp/Networktopologyselect", {
					label
				}).then((_) => {
					if (_.data) {
						_.data.push(this.switchInfo[label]);
						this.disposeData(_);
					} else {
						this.$message.error('系统错误')
					}
				});
			},
			disposeData(value) {
				this.graphData = [];
				this.DataComparison.lastTime = this.DataComparison.thisTime;
				let firstData = value.data.map((item) => {
					return {
						lable: item.lable,
						parentlable: item.parentlable,
						type: item.osType,
						parentlableport: item.parentlableport,
						FAULT: this.isFAULT([item.lable, item.ip]),
						IP: item.ip,
						id: item.hid,
					};
				});
				this.DataComparison.thisTime = firstData.map((item) => {
					return {
						id: item.id,
						FAULT: item.FAULT
					};
				});
				firstData.forEach((item) => {
					if (item.type == "Network") {
						//确定第一层节点
						this.graphData[this.graphData.length] = {
							id: item.id,
							lable: item.lable,
							IP: item.IP,
							NodeType: item.type,
							parentlableport: item.parentlableport,
							FAULT: item.FAULT,
							parentlable: item.parentlable,
							children: [],
						};
					}
				});
				if (this.selectLable) {
					this.graphData = this.graphData.filter((item) => {
						return item.lable === this.selectLable;
					});
				} else {
					this.graphData = this.graphData.filter((item) => {
						return item.parentlable === null
					});
				}
				this.recursionData(this.graphData, firstData);
				if (this.graphData.length === 0) {
					this.$message({
						type: 'error',
						duration: 5000,
						message: '数据错误!!!',
						showClose: true,
					})
				} else {
					this.renderChart(this.graphData[0]);
				}

			},
			recursionData(pData, mData) {
				let outside = [];
				mData.forEach((item) => {
					pData.forEach((pItem) => {
						if (pItem.lable == item.parentlable) {
							// 查找是否存在 不存在才添加
							if (
								pItem.children.findIndex((fItem) => fItem.lable == item.lable) ==
								-1
							) {
								pItem.children.push({
									id: item.id,
									lable: item.lable,
									IP: item.IP,
									NodeType: item.type,
									parentlableport: item.parentlableport,
									FAULT: item.FAULT,
									children: [],
								});
							}
						} else {
							outside.push(item);
						}
					});
				});
				if (outside.length > 0) {
					pData.forEach((item) => {
						this.recursionData(item.children, outside);
					});
				}
			},
			renderChart(data) {
				if (this.firstPage) {
					this.graph.data(data);
					this.graph.render();
					this.graph.fitView();
				} else {
					this.dataValidation();
				}
			},
			// changeData(index,id) {
			//   if(index==null){
			//     this.graphData.forEach((item,itemIndex)=>{
			//       if(item.id===id){
			//         index = itemIndex;
			//       }
			//     })
			//   }
			//   this.selectIndex = index;
			//   this.firstPage = true;
			//   this.renderChart(this.graphData[this.selectIndex]);
			// },
			InitChart() {
				const container = document.getElementById("container");
				const width = container.scrollWidth || 1080;
				const height = container.scrollHeight || 800;
				this.graph = new G6.TreeGraph({
					container: "container",
					width,
					height,
					data: [],
					// linkCenter: true,
					// fitCenter: true,
					fitView: true,
					fitViewPadding: 100,
					autoPaint: false,
					modes: {
						default: [
							// {
							//   type: "collapse-expand",
							//   onChange: function onChange(item, collapsed) {
							//     const data = item.get("model");
							//     data.collapsed = collapsed;
							//     return true;
							//   },
							// },
							"drag-node",
							// {
							//   type: "zoom-canvas",
							//   sensitivity: 1,
							//   shouldUpdate(e) {
							//     e.stopPropagation()
							//     return true;
							//   },
							// },
							{
								type: "tooltip",
								formatText(model) {
									return `
                <div style="color:#fff;background:#2c3e50;border: 1px solid #e2e2e2;border-radius: 4px;padding:5px">
                  标签：${model.label},<br/>
                  网口：${
                    model.parentlableport ? model.parentlableport : "无"
                  },<br/>
                  IPv4 地址:${model.IP}
                </div>
                `;
								},
							},
							{
								type: "edge-tooltip",
								formatText(model) {
									return `
                <div style="color:#fff;background:#2c3e50;border: 1px solid #e2e2e2;border-radius: 4px;padding:5px">
                ${model.source} <==> ${model.target}
                </div>`;
								},
							},
							{
								type: "activate-relations",
								trigger: "mouseenter",
								activeState: "active",
							},
						],
					},

					defaultNode: {
						type: "dom-node",
						size: [50, 30],
					},
					defaultEdge: {
						type: "line-dash",
						style: {
							stroke: "#27ae60",
							lineWidth: 3,
						},
					},
					layout: {
						type: "dendrogram",
						direction: "LR",
						radial: true,
					},
				});
				this.graph.on("click", (e) => {
					if (e.item && e.item["_cfg"].model.NodeType === "Network") {
						this.getInfo(e.item["_cfg"].model.lable);
						this.firstPage = true;
						this.isTopFloor = false;
						this.addHistoryItem(e.item["_cfg"].model.lable);
					}
				});

				this.graph.node(function(node) {
					return {
						label: node.lable,
						width: node.size[0],
						height: node.size[1],
						// img: PNG,
						labelCfg: {
							position: "bottom",
							style: {
								fill: "#000",
							},
						},
					};
				});
				// this.graph.on("wheelzoom", (e) => {
				//   e.stopPropagation();
				// });

				if (typeof window !== "undefined")
					window.onresize = () => {
						if (!this.graph || this.graph.get("destroyed")) return;
						if (!container || !container.scrollWidth || !container.scrollHeight)
							return;
						this.graph.changeSize(container.scrollWidth, container.scrollHeight);
					};
			},
			getFailedNode() {
				getJavaServerNotData("/Sp/Networktopoalert")
					.then((_) => {
						console.log(_,'什么')
						if (_) {
							let data = _.map(({
								ip,
								lable,
								osType
							}) => {
								return [lable, ip, osType];
							});
							this.config = {
								data: data
							};
						}
					})
					.finally((_) => {
						if (this.isTopFloor) {
							this.getSwitchInfo();
						} else {
							this.getInfo(this.selectLable);
						}
						// this.getInfo();
					});
			},
			isFAULT(arg) {
				let status = this.config.data.filter(([label, ip]) => {
					return label === arg[0] && ip === arg[1];
				});
				return status.length > 0 ? true : false;
			},
			changeItem(id, FAULT) {
				const item = this.graph.findById(id);
				if (item) {
					const m = JSON.parse(JSON.stringify(item._cfg.model));
					m.FAULT = FAULT;
					this.graph.updateItem(item, m);
					const edges = this.graph.getEdges();
					const edge = edges.filter(
						(item) => item["_cfg"].target["_cfg"].id == id
					);
					//更新父节点
					if (edge.length) {
						const shape = edge[0]["_cfg"]["keyShape"];
						if (
							edge[0]["_cfg"].targetNode["_cfg"].model.FAULT ||
							edge[0]["_cfg"].sourceNode["_cfg"].model.FAULT
						) {
							shape.stopAnimate();
							// 清空 lineDash
							shape.attr("lineDash", null);
							shape.attrs.stroke = "#e74c3c";
						} else {
							shape.attrs.stroke = "#27ae60";
							let index = 0;
							shape.animate(
								() => {
									index++;
									if (index > 9) {
										index = 0;
									}
									const res = {
										lineDash,
										lineDashOffset: -index,
									};
									return res;
								}, {
									repeat: true,
									duration: 3000,
								}
							);
						}
					} else {
						//子节点
						const edge = edges.filter(
							(item) => item["_cfg"].source["_cfg"].id == id
						);
						edge[0]["_cfg"].sourceNode["_cfg"].edges.forEach((item) => {
							const shape = item["_cfg"]["keyShape"];
							if (
								item["_cfg"].targetNode["_cfg"].model.FAULT ||
								item["_cfg"].sourceNode["_cfg"].model.FAULT
							) {
								shape.stopAnimate();
								// 清空 lineDash
								shape.attr("lineDash", null);
								shape.attrs.stroke = "#e74c3c";
							} else {
								shape.attrs.stroke = "#27ae60";
								let index = 0;
								shape.animate(
									() => {
										index++;
										if (index > 9) {
											index = 0;
										}
										const res = {
											lineDash,
											lineDashOffset: -index,
										};
										return res;
									}, {
										repeat: true,
										duration: 3000,
									}
								);
							}
						});
						// if (
						//   edge[0]["_cfg"].targetNode["_cfg"].model.FAULT ||
						//   edge[0]["_cfg"].sourceNode["_cfg"].model.FAULT
						// ) {
						//   shape.attrs.stroke = "#e74c3c";
						// } else {
						//   shape.attrs.stroke = "#27ae60";
						//   let index = 0;
						//   shape.animate(
						//     () => {
						//       index++;
						//       if (index > 9) {
						//         index = 0;
						//       }
						//       const res = {
						//         lineDash,
						//         lineDashOffset: -index,
						//       };
						//       return res;
						//     },
						//     {
						//       repeat: true,
						//       duration: 3000,
						//     }
						//   );
						// }
					}
				}
			},
			dataValidation() {
				let {
					lastTime,
					thisTime
				} = this.DataComparison;
				let findItem;
				let temp = thisTime.filter((item) => {
					findItem = lastTime.find((_) => {
						return _.id === item.id;
					});
					if (findItem && findItem.FAULT !== item.FAULT) {
						return item;
					}
				});
				temp.forEach((item) => this.changeItem(item.id, item.FAULT));
			},
			TopFloor() {
				this.isTopFloor = true;
				this.firstPage = true;
				this.getSwitchInfo();
			},
			selectHistoryItem(item) {
				this.firstPage = true;
				if (item === "顶层网络拓扑") {
					this.isTopFloor = true;
					this.selectLable = "";
					this.getSwitchInfo();
				} else {
					this.getInfo(item);
				}
			},
			addHistoryItem(item) {
				this.history.push(item);
				this.history = [...new Set(this.history)];
			},
			getBusiness() {
				let _postData = {
					opera: "GetServicesName",
					curPage: 1,
					pageSize: 10000,
					sort: {
						sortColumn: "",
						sortOrders: "",
					},
					filtersType: "exactquery", // 精确查询
					filters: {
						NAME: "",
					},
				};
				submitAdmin({
					postData: JSON.stringify(_postData),
				}).then((res) => {
					console.log(res,'dasd')
					this.Business = res.data;
				});
			},
			selectBusiness(bid) {
				this.popoverLoading = true;
				getJavaServerData("/Sp/businesselect", {
						bid
					})
					.then((_) => {
						console.log('服务器',_)
						if (_.data.length) {
							this.popoverData = _.data;
						}
					})
					.finally(() => {
						this.popoverLoading = false;
					});
			},
			closePopover() {
				this.popoverData = [];
			},
		},
		watch: {},
		beforeDestroy() {
			bus.$off(this.timerEventName);
			this.graph.destroy();
		},
	};
</script>

<style scoped lang="scss">
	.selectCon {
		display: flex;
		width: 100%;
		flex-direction: column;
		height: 100%;
		background: #44444421;
		// align-items: center;
		border-top-left-radius: 5px;
		border-top-right-radius: 5px;
	}

	.selectHead {
		width: 100%;
		height: 30px;
		background: #2980b9;
		color: #fff;
		display: grid;
		align-items: center;
		justify-items: center;
		margin-bottom: 5px;
		border-top-left-radius: 5px;
		border-top-right-radius: 5px;
		font-weight: 600;
		font-size: 12px;
	}

	.select {
		width: 80px;
		padding: 5px;
		margin-bottom: 5px;
		cursor: pointer;
		border: 0;
		word-break: normal;
		word-wrap: break-word;
		padding: 5px;
		color: #fff;
		font-weight: 500;
		background: #3498db;
		border-radius: 5px;
		font-size: 12px;
	}

	.selectMain {
		max-height: 87vh;
		overflow-y: scroll;
	}

	.selected {
		background: red;
	}

	.select-con {
		display: grid;
		width: 100%;
		justify-content: center;
	}

	.con {
		display: grid;
		grid-template-columns: 100px auto 300px;
		position: relative;
	}

	.warnCon {
		background: #44444421;
		width: 100%;
		height: 90vh;
	}

	.warnCon .head {
		height: 30px;
		width: 100%;
		display: grid;
		justify-items: center;
		align-items: center;
		background: #2980b9;
		color: #fff;
		font-weight: 600;
	}

	.warnCon .contain {
		display: grid;
		grid-template-columns: repeat(5, 1fr);
		max-height: 700px;
		overflow-y: scroll;
	}

	.warnCon .contain div {
		display: flex;
		justify-content: center;
	}

	.g6-tooltip {
		padding: 10px 6px;
		color: #444;
		background-color: rgba(117, 25, 25, 0.9);
		border: 1px solid #e2e2e2;
		border-radius: 4px;
	}

	.selectMain::-webkit-scrollbar {
		width: 1px;
		height: 1px;
	}

	.selectMain::-webkit-scrollbar-thumb {
		background-color: rgba(4, 44, 119, 0.7);
		border-radius: 3px;
	}

	.contain::-webkit-scrollbar {
		width: 1px;
		height: 1px;
	}

	.contain::-webkit-scrollbar-thumb {
		background-color: rgba(4, 44, 119, 0.7);
		border-radius: 3px;
	}

	.toTop {
		position: fixed;
		top: 60px;
		left: 300px;
		background: #50585e;
		color: #fff;
		height: 30px;
		width: 50px;
	}

	.popoverCon {
		display: flex;
		flex-direction: row;
		flex-wrap: wrap;
	}

	.popoverCon div {
		width: 50px;
		height: 50px;
		display: flex;
		justify-content: center;
		align-items: center;
		margin: 6px 1px;
	}

	.graphContainer {
		display: grid;
		grid-template-rows: 30px auto;

		.graphHead {
			width: 100%;
			height: 100%;
			display: grid;
			background: #ecf0f1;
			justify-content: center;
			position: relative;

			/deep/ .el-popover__reference {
				height: 100%;
			}

			.title {
				background: #2980b9;
				width: 150px;
				height: 100%;
				color: #fff;
				display: grid;
				align-items: center;
				justify-items: center;
				font-size: 14px;
				border-top-left-radius: 5px;
				border-top-right-radius: 5px;
				cursor: pointer;
			}

			.goBack {
				position: absolute;
				right: 5px;
				font-size: 14px;
				height: 100%;
				background: #e74c3c;
				color: #fff;
				border-radius: 5px;
				display: grid;
				justify-items: center;
				align-items: center;
				padding: 0 5px;
				cursor: pointer;
			}

			.moreGraphData {
				position: absolute;
				left: 5px;
				font-size: 14px;
				height: 100%;
				background: #e67e22;
				color: #fff;
				border-radius: 5px;
				display: grid;
				justify-items: center;
				align-items: center;
				padding: 0 5px;
				cursor: pointer;
			}
		}
	}
</style>
